package com.ff.xyh.consumer.online.user.handler;

import com.ff.xyh.common.entity.message.RoomBanned;
import com.ff.xyh.common.entity.message.RoomMessage;
import com.ff.xyh.common.entity.post.PostJoiner;
import com.ff.xyh.common.entity.post.PostRoom;
import com.ff.xyh.common.entity.post.PostShop;
import com.ff.xyh.common.entity.post.PostTravel;
import com.ff.xyh.common.entity.userfront.FrontUser;
import com.ff.xyh.common.utils.CommonUtil;
import com.ff.xyh.common.vo.message.ActionTypeAndRoomMessage;
import com.ff.xyh.common.vo.message.RoomMessageVo;
import com.ff.xyh.common.vo.user.UserBaseInfo;
import com.ff.xyh.consumer.online.user.config.UserRabbitConfig;
import com.ff.xyh.consumer.online.user.config.Users;
import com.ff.xyh.consumer.online.user.controller.OnlineUserController;
import com.ff.xyh.feign.client.message.RoomBannedClient;
import com.ff.xyh.feign.client.message.RoomMessageClient;
import com.ff.xyh.feign.client.post.PostClient;
import com.ff.xyh.feign.client.post.PostJoinerClient;
import com.ff.xyh.feign.client.post.PostRoomClient;
import com.ff.xyh.feign.client.userfront.FrontUserClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Auther FF
 * @Date 2022年 12月 28日
 * @Time 16:22
 */

@Component
public class UserActionHandler {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private FrontUserClient frontUserClient;

    @Autowired
    private RoomMessageClient roomMessageClient;

    @Autowired
    private RoomBannedClient roomBannedClient;

    @Autowired
    private PostRoomClient postRoomClient;

    @Autowired
    private PostJoinerClient postJoinerClient;

    @Autowired
    private PostClient postClient;


    /**
     * 未知行为类型，只发生在当前服务器下
     * @param message
     */
    public void unknownAction(ActionTypeAndRoomMessage message) {
        RoomMessageVo roomMessageVo = CommonUtil.getMessageInMap(message.getMessageBody(), RoomMessageVo.class);
        String userId = roomMessageVo.getUserId();
        ActionTypeAndRoomMessage messageToUser =
                ActionTypeAndRoomMessage.type(0)
                        .data("message", new RoomMessageVo()
                                .setToUserId(userId)
                                .setMessage("未知消息类型，连接将断开")
                        );
        OnlineUserController user = Users.getUsers().get(userId);
        if (user != null) {
            user.getSession().getAsyncRemote().sendObject(messageToUser);
        }
    }

    /**
     * 评论
     * @param message
     */
    public void commentAction(ActionTypeAndRoomMessage message) {

    }

    /**
     * 收藏
     * @param message
     */
    public void collectAction(ActionTypeAndRoomMessage message) {

    }

    /**
     * 点赞
     * @param message
     */
    public void clickLikeAction(ActionTypeAndRoomMessage message) {

    }

    /**
     * 关注
     * @param message
     */
    public void followAction(ActionTypeAndRoomMessage message) {

    }

    /**
     * 进入群聊 5
     * @param message
     */
    public void inRoomAction(ActionTypeAndRoomMessage message) {
        RoomMessageVo messageVo = getMessageVo(message);
        String roomId = messageVo.getRoomId();
        String userId = messageVo.getUserId();
        System.out.println("inRoomAction got message ==> " + message);
        // 是发送给用户的消息
        if (!StringUtils.isEmpty(messageVo.getToUserId())) {
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    message);
            return ;
        }

        ActionTypeAndRoomMessage messageToUser = ActionTypeAndRoomMessage
                .type(message.getActionType());

        PostRoom postRoom = CommonUtil.getDataInResultObject(
                postRoomClient.getPostRoomById(roomId),
                PostRoom.class);
        // 群聊不存在 进入失败
        if (postRoom == null) {
            messageToUser.setActionType(7)
                    .data("message", new RoomMessageVo()
                            .setRoomId(roomId)
                            .setToUserId(userId)
                            .setMessage("群聊并不存在，无法进入")
                    );
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return ;
        }

//        禁入用户应该也能看消息 只是不能发言
//        RoomBanned roomBanned = MyStringUtil.getDataInResultObject(
//                roomBannedClient.getRoomBannedByRoomIdAndBanner(roomId, userId),
//                RoomBanned.class);
//        // 存在禁入信息 进入失败
//        if (roomBanned != null) {
//            messageToUser.setActionType(7)
//                    .data("message", new RoomMessageVo()
//                            .setRoomId(roomId)
//                            .setToUserId(userId)
//                            .setMessage("您已被禁止进入该群聊！"));
//            rabbitTemplate.convertAndSend(
//                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
//                    UserRabbitConfig.ROUTING_KEY_USER,
//                    messageToUser);
//            return ;
//        }


//        帖子不存在或不可聊天时 群聊不应该被使用
        String postId = postRoom.getPostId();
        Integer postType = postRoom.getPostType();
        int postStatus = -1;
        if (postType == 1) {
            PostShop post = CommonUtil.getDataInResultObject(
                    postClient.getPostShopById(postId), PostShop.class);
            if (post != null) {
                postStatus = post.getPostStatus();
            }
        } else if (postType == 2) {
            PostTravel post = CommonUtil.getDataInResultObject(
                    postClient.getPostTravelById(postId), PostTravel.class);
            if (post != null) {
                postStatus = post.getPostStatus();
            }
        } else {
            messageToUser.setActionType(7)
                    .data("message", new RoomMessageVo()
                            .setRoomId(roomId)
                            .setToUserId(userId)
                            .setMessage("群聊信息有问题，无法进入！"));
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return ;
        }

        if (postStatus == -1 || postStatus == 4) {
            messageToUser.setActionType(7)
                    .data("message", new RoomMessageVo()
                            .setRoomId(roomId)
                            .setToUserId(userId)
                            .setMessage("当前群聊对应的帖子已失效，进入失败！"));
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return ;
        }

        UserBaseInfo user = CommonUtil.getDataInResultObject(
                frontUserClient.getUserBaseInfoById(userId),
                UserBaseInfo.class);
        if (user == null) {
            messageToUser.setActionType(7)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("用户信息有误！"));
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return ;
        }

        if (! redisTemplate.hasKey(roomId)) { // 群聊列表不存在 则将群聊列表创建后反馈给用户即可
            redisTemplate.opsForSet().add(roomId, userId);
            if (redisTemplate.boundSetOps(roomId).size()>0) { // 大于0 进入成功
                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        UserRabbitConfig.ROUTING_KEY_USER,
                        ActionTypeAndRoomMessage.type(6)
                                .data("message", new RoomMessageVo()
                                        .setToUserId(userId)
                                        .setRoomId(roomId)
                                        .setUserNumber(1)
                                        .setMessage("您已进入群聊")));
            }
            return ;
        }

        // roomId Set 已存在
        BoundSetOperations roomUserSetOps = redisTemplate.boundSetOps(roomId);
        Set<String> roomUsers = roomUserSetOps.members(); // 获取集合中的元素
        int size = roomUsers.size() + 1; // 后面要加上刚加入的用户
        RoomMessageVo roomMessageVoToUser = new RoomMessageVo();
        roomMessageVoToUser
                .setRoomId(roomId)
                .setUserNumber(size)
                .setUserId(userId)
                .setUserNickname(user.getNickname())
                .setUserAvatar(user.getAvatar())
                .setMessage("用户: " + user.getNickname() + " 进入房间");
        messageToUser.data("message", roomMessageVoToUser);
//            messageToUser.setActionType(message.getActionType()) 已经设置
        String userIdAndMessageRoutingKey = userId +
                UserRabbitConfig.ROUTING_KEY_MESSAGE;
        boolean isAdded = false;
        if (! redisTemplate.hasKey(userIdAndMessageRoutingKey)) {
            // 没加入过任何群聊 则需要新建一个set集合
            redisTemplate.opsForSet().add(userIdAndMessageRoutingKey, roomId);
            isAdded = true;
        }
        BoundSetOperations userExistRoomSetOps = redisTemplate.boundSetOps(userIdAndMessageRoutingKey);
        if (isAdded || userExistRoomSetOps.add(roomId) > 0) { // 用户进入过的房间集合 刚刚添加过了或者添加成功
            if (roomUserSetOps.add(userId) > 0) { // 成功添加用户id到房间集合
                // 添加到set集合 进入成功
                // 通知已存在的用户
                for (String roomUserId : roomUsers) {
                    roomMessageVoToUser.setToUserId(roomUserId);
                    String roomUserMessageRoutingKey = (String) redisTemplate.opsForValue().get("online" + roomUserId);
                    if (!StringUtils.isEmpty(roomUserMessageRoutingKey)) {
                        rabbitTemplate.convertAndSend(
                                UserRabbitConfig.EXCHANGE_DIRECT_USER,
                                roomUserMessageRoutingKey, // 发送到服务器的routingKey 但是还不是用户的routingKey 需要转发
                                messageToUser);
                    }
                }
                // 反馈给进入者
                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        UserRabbitConfig.ROUTING_KEY_USER,
                        ActionTypeAndRoomMessage.type(6)
                                .data("message", roomMessageVoToUser
                                        .setToUserId(userId)
                                        .setMessage("您已进入群聊")));
            } else {
                // 添加到set集合失败 可能是用户原本就属于群聊人员
                boolean isJoiner = false; // 参与者
                boolean isOwner = postRoom.getUserId().equals(userId); // 拥有者
                if (!isOwner) { // 不是拥有者
                    PostJoiner joiner = CommonUtil.getDataInResultObject(
                            postJoinerClient.getPostJoinerWithPostIdAndTypeAndUserId(
                                    postId, postType, userId, false),
                            PostJoiner.class);
                    if (joiner != null) {
                        isJoiner = true;
                    }
                }
                // 如果是群主或群成员 则尝试性添加到监听的集合
                if (isOwner || isJoiner) {
                    userExistRoomSetOps.add(roomId);
                    roomUserSetOps.add(userId);
                    rabbitTemplate.convertAndSend(
                            UserRabbitConfig.EXCHANGE_DIRECT_USER,
                            UserRabbitConfig.ROUTING_KEY_USER,
                            ActionTypeAndRoomMessage.type(6)
                                    .data("message", roomMessageVoToUser
                                            .setToUserId(userId)
                                            .setMessage("您已进入群聊")));
                } else {
                    userExistRoomSetOps.remove(roomId); // 尝试性删除一下
                    roomUserSetOps.remove(userId); // 尝试性删除一下
                    rabbitTemplate.convertAndSend(
                            UserRabbitConfig.EXCHANGE_DIRECT_USER,
                            UserRabbitConfig.ROUTING_KEY_USER,
                            ActionTypeAndRoomMessage.type(7)
                                    .data("message", roomMessageVoToUser
                                            .setMessage("进入失败，未知错误")));
                }
            }

        } else {
            // 添加到set集合失败 可能是用户原本就属于群聊人员
            boolean isJoiner = false; // 参与者
            boolean isOwner = postRoom.getUserId().equals(userId); // 拥有者
            if (!isOwner) { // 不是拥有者
                List<PostJoiner> postJoiners = CommonUtil.getItemsInResultObject(
                        postJoinerClient.getAcceptedPostJoinersWithPostIdAndPostType(
                                postId, postType),
                        PostJoiner.class);
                // 申请之后不用自动监听消息
                List<PostJoiner> askedJoiners = CommonUtil.getItemsInResultObject(
                        postJoinerClient.getPostJoinerListByUserIdAndJoinerStatus(
                                0, userId),
                        PostJoiner.class);
                if (askedJoiners != null) {
                    postJoiners.addAll(askedJoiners);
                }
                List<PostJoiner> joiners = postJoiners.stream().filter(joiner ->
                                joiner.getPostId() == postId
                                &&
                                joiner.getPostType() == postType)
                        .collect(Collectors.toList());

                if (joiners != null || ! joiners.isEmpty()) {
                    isJoiner = true;
                }
//                改用流处理
//                for (PostJoiner joiner : joiners) {
//                    if (joiner.getUserId().equals(userId)) {
//                        isJoiner = true;
//                    }
//                }
            }
            if (isOwner || isJoiner) { // 如果是群主或群成员 则不需要再进入 可以反馈给前端已进入

                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        UserRabbitConfig.ROUTING_KEY_USER,
                        ActionTypeAndRoomMessage.type(6)
                                .data("message", roomMessageVoToUser
                                        .setToUserId(userId)
                                        .setMessage("您已进入群聊")));
            } else {
                userExistRoomSetOps.remove(roomId); // 尝试性删除一下
                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        UserRabbitConfig.ROUTING_KEY_USER,
                        ActionTypeAndRoomMessage.type(7)
                                .data("message", roomMessageVoToUser
                                        .setMessage("进入失败，未知错误")));
            }
        }
    }

//    public void inRoomSuccess(ActionTypeAndRoomMessage message) {
//    }

//    public void inRoomFailed(ActionTypeAndRoomMessage message) {
//    }

    /**
     * 8 退出群聊
     *      已接受和申请中的用户 会继续监听消息
     * @param message
     */
    public void outRoomAction(ActionTypeAndRoomMessage message) {
        RoomMessageVo messageVo = getMessageVo(message);
        String roomId = messageVo.getRoomId(); // 群聊
        String userId = messageVo.getUserId(); // 退出的用户

        // 是发送给用户的消息
        if (!StringUtils.isEmpty(messageVo.getToUserId())) {
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    message);
            return ;
        }


        ActionTypeAndRoomMessage messageToUser = ActionTypeAndRoomMessage
                .type(message.getActionType());

        // 用户基础信息
        UserBaseInfo user = CommonUtil.getDataInResultObject(
                frontUserClient.getUserBaseInfoById(userId),
                UserBaseInfo.class);
        if (user == null) {
            messageToUser.setActionType(0)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("用户信息有误！"));
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return;
        }

        PostRoom postRoom = CommonUtil.getDataInResultObject(
                postRoomClient.getPostRoomById(roomId),
                PostRoom.class);
        // 群聊不存在
        if (postRoom == null) {
            messageToUser.setActionType(7)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("群聊并不存在, 消息发送失败")
                    );
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return ;
        }
        // 添加到set集合失败 可能是用户原本就属于群聊人员
        boolean isJoiner = false; // 参与者
        boolean isOwner = postRoom.getUserId().equals(userId); // 拥有者
        if (!isOwner) { // 不是拥有者 则如果是有效的参与者
            List<PostJoiner> joiners = CommonUtil.getItemsInResultObject(
                    postJoinerClient.getEffectivePostJoinersWithPostIdAndPostType(
                            postRoom.getPostId(),
                            postRoom.getPostType()),
                    PostJoiner.class);
            List<PostJoiner> nowJoinerInList = joiners.stream().filter(joiner ->
                            userId.equals(joiner.getUserId()))
                    .collect(Collectors.toList());
            if (nowJoinerInList != null && !nowJoinerInList.isEmpty()) {
                isJoiner = true;
            }
//            for (PostJoiner joiner : joiners) {
//                if (joiner.getUserId().equals(userId)) {
//                    isJoiner = true;
//                }
//            }
        }
        if (isOwner || isJoiner) { // 如果是群主或群成员 则不需要退出
            return ;
        }
        String userIdAndMessageRoutingKey = userId + UserRabbitConfig.ROUTING_KEY_MESSAGE;
        if (redisTemplate.hasKey(userIdAndMessageRoutingKey)) {
            redisTemplate.boundSetOps(userIdAndMessageRoutingKey).remove(roomId);
        }


        BoundSetOperations roomUsersSetOps = redisTemplate.boundSetOps(roomId);
        Set<String> roomUsers = roomUsersSetOps.members();
//        不包含 则直接返回
        if (! roomUsers.contains(userId)) {
            return ;
        }
        int size = roomUsers.size() - 1;
        System.out.println("now size : " + size);
        roomUsersSetOps.remove(userId);
        roomUsers.remove(userId);

        RoomMessageVo roomMessageVoToUser = new RoomMessageVo();
        roomMessageVoToUser
                .setRoomId(roomId)
                .setUserNickname(user.getNickname())
                .setUserAvatar(user.getAvatar())
                .setUserNumber(size)
                .setMessage("用户: " + user.getNickname() + " 离开房间");
        messageToUser.data("message", roomMessageVoToUser);
        System.out.println("roomUsers ===> " + roomUsers);
        // 通知用户
        for (String roomUserId : roomUsers) {
            roomMessageVoToUser.setToUserId(roomUserId);
            System.out.println("ddddd========>" + roomMessageVoToUser);
            String roomUserRoutingKey = (String) redisTemplate.opsForValue().get("online" + roomUserId);
            if (!StringUtils.isEmpty(roomUserRoutingKey)) {
                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        roomUserRoutingKey, // 发送到服务器的routingKey 但是还不是用户的routingKey 需要转发
                        messageToUser);
            }
        }

    }

    /**
     * 发送消息 9
     * @param message
     */
    public void sendMessage(ActionTypeAndRoomMessage message) {

        RoomMessageVo messageVo = getMessageVo(message);
        String roomId = messageVo.getRoomId(); // 群聊
        String userId = messageVo.getUserId(); // 发消息用户

        // 是发送给用户的消息
        if (!StringUtils.isEmpty(messageVo.getToUserId())) {
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    message);
            return ;
        }

        ActionTypeAndRoomMessage messageToUser = ActionTypeAndRoomMessage
                .type(message.getActionType());

        // 用户基础信息
        UserBaseInfo user = CommonUtil.getDataInResultObject(
                frontUserClient.getUserBaseInfoById(userId),
                UserBaseInfo.class);
        if (user == null) {
            messageToUser.setActionType(11)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("用户信息有误！"));
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return;
        }
        //判断群聊是否存在
        PostRoom room = CommonUtil.getDataInResultObject(
                postRoomClient.getPostRoomById(roomId), PostRoom.class);
        if (room == null) {
            messageToUser.setActionType(11)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("群聊信息不存在！"));
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return;
        }

        //判断是否可发言
        if (!userId.equals(room.getUserId())) { // 不是群聊拥有者
            PostJoiner speakableJoiner = CommonUtil.getDataInResultObject(
                    postJoinerClient.getPostJoinerWithPostIdAndTypeAndUserId(
                            room.getPostId(),
                            room.getPostType(),
                            userId,
                            true), PostJoiner.class);
            if (speakableJoiner == null) { // 也不是已被接受的群聊参与者
                messageToUser.setActionType(11)
                        .data("message", new RoomMessageVo()
                                .setToUserId(userId)
                                .setMessage("没有权限！"));
                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        UserRabbitConfig.ROUTING_KEY_USER,
                        messageToUser);
                return;
            }
        }
//        判断是否被禁止进入
        if (CommonUtil.getDataInResultObject(
                roomBannedClient.getRoomBannedByRoomIdAndBanner(roomId, userId),
                RoomBanned.class) != null) {
            messageToUser.setActionType(11)
                    .data("message", new RoomMessageVo()
                            .setRoomId(roomId)
                            .setToUserId(userId)
                            .setMessage("您已被踢出群聊。没有权限！"));
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return;
        }

        RoomMessage roomMessage = new RoomMessage();
        roomMessage
                .setRoomId(messageVo.getRoomId())
                .setUserId(messageVo.getUserId())
                .setMessage(messageVo.getMessage());

        // 应该先将消息发送到数据库然后得到消息的id 再发送给用户 如果数据库添加消息失败 则反馈给前端
        RoomMessage savedRoomMessage = CommonUtil.getDataInResultObject(
                roomMessageClient.addMessage(roomMessage), RoomMessage.class);
        if (savedRoomMessage == null) { // 保存失败
            messageToUser.setActionType(11)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("消息发送失败")
                    );
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return ;
        }

        // 获得群聊用户
        BoundSetOperations roomUsersSetOps = redisTemplate.boundSetOps(roomId);
        Set<String> roomUsers = roomUsersSetOps.members();

        RoomMessageVo roomMessageVoToUser = new RoomMessageVo();
        BeanUtils.copyProperties(savedRoomMessage, roomMessageVoToUser);
        messageToUser.data("message", roomMessageVoToUser
                .setUserAvatar(user.getAvatar())
                .setUserNickname(user.getNickname())
        );
        // 通知用户
        for (String roomUserId : roomUsers) {
            if (roomUserId.equals(userId)) {
                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        UserRabbitConfig.ROUTING_KEY_USER, // 发送到服务器的routingKey 但是还不是用户的routingKey 需要转发
                        ActionTypeAndRoomMessage.type(10).data(
                                "message", roomMessageVoToUser
                                        .setToUserId(userId))
                );
                continue;
            }
            roomMessageVoToUser.setToUserId(roomUserId);
            String roomUserRoutingKey = (String) redisTemplate.opsForValue().get("online" + roomUserId);
            if (!StringUtils.isEmpty(roomUserRoutingKey)) {
                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        roomUserRoutingKey, // 发送到服务器的routingKey 但是还不是用户的routingKey 需要转发
                        messageToUser);
            }
        }



    }

//    public void sendMessageSuccess(ActionTypeAndRoomMessage message) {
//
//    }
//    public void sendMessageFailed(ActionTypeAndRoomMessage message) {
//
//    }

    /**
     * 12 踢出用户 => 改为禁言
     * @param message
     */
    public void kickRoomUser(ActionTypeAndRoomMessage message) {
        ActionTypeAndRoomMessage messageToUser = ActionTypeAndRoomMessage.type(message.getActionType());
        RoomMessageVo messageVo = getMessageVo(message);
        String roomId = messageVo.getRoomId(); // 群聊
        String userId = messageVo.getUserId(); // 发出用户
        String bannerId = messageVo.getToUserId(); // 被踢者

        // 是发送给用户的消息
        if (!StringUtils.isEmpty(userId) && userId.equals(messageVo.getToUserId())) {
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    message);
            return ;
        }

        PostRoom postRoom = CommonUtil.getDataInResultObject(postRoomClient.getPostRoomById(roomId), PostRoom.class);
        UserBaseInfo operator = CommonUtil.getDataInResultObject(frontUserClient.getUserBaseInfoById(userId), UserBaseInfo.class);
        UserBaseInfo banner = CommonUtil.getDataInResultObject(frontUserClient.getUserBaseInfoById(bannerId), UserBaseInfo.class);

        if (postRoom == null || operator == null || banner == null) {
            messageToUser.setActionType(14)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("参数错误，踢出失败")
                    );
            // 给踢人者
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return ;
        }
        // 不是群聊拥有者 看看是否为参与者 如果是 则需要将其踢出拼单 此时需要考虑拼单状态
        if (!postRoom.getUserId().equals(userId)) {
            String postId = postRoom.getPostId();
            Integer postType = postRoom.getPostType();
            PostJoiner joiner = CommonUtil.getDataInResultObject(
                    postJoinerClient.getPostJoinerWithPostIdAndTypeAndUserId(
                            postId , postType, userId, false),
                    PostJoiner.class);
            if (joiner != null) { // 是参与者
                if (postType == 1) { // 拼购帖
                    PostShop post = CommonUtil.getDataInResultObject(
                            postClient.getPostShopById(postId),
                            PostShop.class);
                    if (post.getPostStatus() == 2 || post.getPostStatus() == 3) {
                        messageToUser.setActionType(14)
                                .data("message", new RoomMessageVo()
                                        .setToUserId(userId)
                                        .setMessage("当前帖子状态不允许踢出该用户")
                                );
                        // 给踢人者
                        rabbitTemplate.convertAndSend(
                                UserRabbitConfig.EXCHANGE_DIRECT_USER,
                                UserRabbitConfig.ROUTING_KEY_USER,
                                messageToUser);
                        return ;
                    }
                } else if (postType == 2) { // 旅游贴
                    PostShop post = CommonUtil.getDataInResultObject(
                            postClient.getPostShopById(postId),
                            PostShop.class);
                    if (post.getPostStatus() == 2 || post.getPostStatus() == 3) {
                        messageToUser.setActionType(14)
                                .data("message", new RoomMessageVo()
                                        .setToUserId(userId)
                                        .setMessage("当前帖子状态不允许踢出该用户")
                                );
                        // 给踢人者
                        rabbitTemplate.convertAndSend(
                                UserRabbitConfig.EXCHANGE_DIRECT_USER,
                                UserRabbitConfig.ROUTING_KEY_USER,
                                messageToUser);
                        return ;
                    }
                }

            }
        }

        // 获得群聊中所有用户id 将被禁者删除
        BoundSetOperations roomUserSetOps = redisTemplate.boundSetOps(roomId);
        roomUserSetOps.remove(bannerId);
        Set<String> roomUsers = roomUserSetOps.members(); // 不含 bannerId
        roomUsers.remove(bannerId);
        // 获取被禁者进入过的群聊id 将被禁的群聊删除
        String bannerMessageRoutingKey = (String) redisTemplate.opsForValue().get("online" + bannerId);
        BoundSetOperations userExistRoomSetOps = redisTemplate.boundSetOps(bannerId + bannerMessageRoutingKey);
//        Set<String> userRoomSet = userRoomSetOps.members();
        userExistRoomSetOps.remove(roomId);


        // 给被踢者
        rabbitTemplate.convertAndSend(
                UserRabbitConfig.EXCHANGE_DIRECT_USER,
                bannerMessageRoutingKey,
                ActionTypeAndRoomMessage.type(15)
                        .data("message", new RoomMessageVo()
                                .setToUserId(bannerId)
                                .setRoomId(roomId)
                                .setMessage("您已被踢出房间")));

        RoomBanned roomBanned =
                CommonUtil.getDataInResultObject(roomBannedClient.addRoomBanned(
                        new RoomBanned()
                                .setRoomId(roomId)
                                .setOperatorId(userId)
                                .setBannerId(bannerId)
                ), RoomBanned.class);
        if (roomBanned == null) { // 踢出不生效
            // 给踢人者
            messageToUser.setActionType(14)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("数据保存失败，踢出只在本次生效")
                    );
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
//            // 给被踢者
//            String bannerMessageRoutingKey = (String) redisTemplate.opsForValue().get(bannerId);
//            rabbitTemplate.convertAndSend(
//                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
//                    bannerMessageRoutingKey,
//                    ActionTypeAndRoomMessage.type(15)
//                            .data("message", new RoomMessageVo()
//                                    .setToUserId(bannerId)
//                                    .setRoomId(roomId)
//                                    .setMessage("您已被踢出房间"))
//            );
//
//            return ;
        } else { // 生效

            // 给踢人者
            messageToUser.setActionType(13)
                    .data("message", new RoomMessageVo()
                            .setRoomId(roomId)
                            .setToUserId(userId)
                            .setMessage("踢出成功，用户 " + banner.getNickname() + " 已被踢出群聊")
                    );
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
        }

        RoomMessageVo roomMessageVoToUser = new RoomMessageVo();
        roomMessageVoToUser
                .setRoomId(roomId)
                .setUserNumber(roomUsers.size()-1)
                .setMessage( "用户: " + banner.getNickname() + " 被管理员: " + operator.getNickname() + " 踢出房间");
        messageToUser.data("message", roomMessageVoToUser);
        for (String roomUserId : roomUsers) {
            if (roomUserId.equals(bannerId) || roomUserId.equals(userId))
                continue;

            roomMessageVoToUser.setToUserId(roomUserId).setUserId(roomUserId);
            String roomUserMessageRoutingKey = (String) redisTemplate.opsForValue().get("online" + roomUserId);
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    roomUserMessageRoutingKey,
                    messageToUser.setActionType(12));
        }
    }
//    public void successKick(ActionTypeAndRoomMessage message) {
//
//    }
//    public void failedKick(ActionTypeAndRoomMessage message) {
//
//    }
    public void beingKicked(ActionTypeAndRoomMessage message) {
        // 转发到处理队列
        deliverTheMessage(message);
    }
    public void beingLogin(ActionTypeAndRoomMessage message) {
        deliverTheMessage(message);
    }

    /**
     * 17 下线 需要退出房间 更新用户最后在线时间
     * @param message
     */
    public void loginOff(ActionTypeAndRoomMessage message) {
        RoomMessageVo messageVo = getMessageVo(message);
        String userId = messageVo.getUserId(); // 下线的用户
        String userIdAndMessageRoutingKey =
                userId + UserRabbitConfig.ROUTING_KEY_MESSAGE;
        // 是发送给用户的消息
        if (!StringUtils.isEmpty(messageVo.getToUserId())) {
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    message);
            return ;
        }
        FrontUser user = CommonUtil.getDataInResultObject(
                frontUserClient.updateUserLastLogById(userId), FrontUser.class);
        // 用户不存在
        if (user == null) {
            // 下线操作 用户已经断开连接 不需要反馈错误消息
            return ;
        }



        if (redisTemplate.hasKey(userIdAndMessageRoutingKey)) { // 有存在的群聊
            System.out.println("la=========");
            RoomMessageVo messageVoToUser =
                    new RoomMessageVo()
                        .setUserId(userId)
                        .setUserNickname(user.getNickname())
                        .setUserAvatar(user.getAvatar())
                            .setMessage("用户：" + user.getNickname() + " 已下线.");
            ActionTypeAndRoomMessage messageToUser = ActionTypeAndRoomMessage.type(17)
                    .data("message", messageVoToUser);
            BoundSetOperations userExistRoomSetOps = redisTemplate.boundSetOps(userIdAndMessageRoutingKey);
            Set<String> userExistRoomIdSet = userExistRoomSetOps.members();
            for (String roomId : userExistRoomIdSet) {
                System.out.println("userExistRoomIdSet ==》 " + roomId);
                // 不存在则跳过
                if (! redisTemplate.hasKey(roomId))
                    continue;
                messageVoToUser.setRoomId(roomId);
                BoundSetOperations roomUserIdSetOps = redisTemplate.boundSetOps(roomId);
                if (roomUserIdSetOps != null) {
                    roomUserIdSetOps.remove(userId);
                    Set<String> roomUserIdSet = roomUserIdSetOps.members();
                    if (roomUserIdSet != null) {
                        for (String roomUserId : roomUserIdSet) {
                            System.out.println("roomUserId ==> " + roomUserId);
                            String roomUserMessageRoutingKey =
                                    (String) redisTemplate.opsForValue().get("online" + roomUserId);
                            if (StringUtils.isEmpty(roomUserMessageRoutingKey))
                                continue;
                            System.out.println("下线 messageToUser  ====》 " + messageToUser);
                            messageVoToUser.setToUserId(roomUserId);
                            rabbitTemplate.convertAndSend(
                                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                                    roomUserMessageRoutingKey,
                                    messageToUser);
                        }
                    }
                }
            }
            // 完成以后删除用户进入过的房间集
            redisTemplate.delete(userIdAndMessageRoutingKey);
        }

    }

    /**
     * 18 登录成功
     *      要获取用户拥有的和加入的拼单
     *      将上线消息转发到每个群聊的在线用户的服务器队列
     * @param message
     */
    public void loginSuccess(ActionTypeAndRoomMessage message) {
        RoomMessageVo messageVo = getMessageVo(message);
        String userId = messageVo.getUserId(); // 登录的用户

        ActionTypeAndRoomMessage messageToUser = ActionTypeAndRoomMessage
                .type(message.getActionType());

        // 用户基础信息
        UserBaseInfo user = CommonUtil.getDataInResultObject(
                frontUserClient.getUserBaseInfoById(userId),
                UserBaseInfo.class);
        if (user == null) {
            messageToUser.setActionType(19)
                    .data("message", new RoomMessageVo()
                            .setToUserId(userId)
                            .setMessage("用户信息有误！"));
            rabbitTemplate.convertAndSend(
                    UserRabbitConfig.EXCHANGE_DIRECT_USER,
                    UserRabbitConfig.ROUTING_KEY_USER,
                    messageToUser);
            return;
        }

        List<String> postShopIdList = new ArrayList<>();
        List<String> postTravelIdList = new ArrayList<>();

        String userIdAndMessageRoutingKey =
                userId + UserRabbitConfig.ROUTING_KEY_MESSAGE;
        if (redisTemplate.hasKey(userIdAndMessageRoutingKey)) {
            // 如果事先存在 则先删除 用户存在的房间的集合里的userId
            // 然后删除 用户进入过的房间的集合
            // 不需要通知 因为之后用户上线加入 会自动通知
            Set<String> roomIdSet = redisTemplate.boundSetOps(userIdAndMessageRoutingKey).members();
            for (String roomId : roomIdSet) {
                // 不能直接删除这个roomId 因为可能还有其他在线用户
                redisTemplate.boundSetOps(roomId).remove(userId);
            }
            redisTemplate.delete(userIdAndMessageRoutingKey);
        }

        // 获得群聊用户
//        BoundSetOperations roomUserSetOps = redisTemplate.boundSetOps(roomId);
//        roomUserSetOps.remove(bannerId);
//        Set<String> roomUsers = roomUserSetOps.members(); // 不含 bannerId
//        roomUsers.remove(bannerId);
        // 用户参与申请参与的拼单和用户已经接受了的拼单
        List<PostJoiner> joinerList = new ArrayList<>();
        List<PostJoiner> acceptedJoinerList = CommonUtil.getItemsInResultObject(
                postJoinerClient.getPostJoinerListByUserIdAndJoinerStatus(
                        -1, userId),
                PostJoiner.class);
        if (acceptedJoinerList != null) {
            joinerList.addAll(acceptedJoinerList);
        }
        List<PostJoiner> askedJoinerList = CommonUtil.getItemsInResultObject(
                postJoinerClient.getPostJoinerListByUserIdAndJoinerStatus(
                        0, userId),
                PostJoiner.class);
        if (askedJoinerList != null) {
            joinerList.addAll(askedJoinerList);
        }
//        System.out.println(joinerList);

        if (joinerList != null && !joinerList.isEmpty()) {
            // 拼购帖
            List<PostJoiner> postShopJoiners = joinerList.stream()
                    .filter(joiner -> joiner.getPostType() == 1).collect(Collectors.toList());
            if (postShopJoiners != null && !postShopJoiners.isEmpty()) {
                // 它不为空 则他的Id是有的
                postShopIdList.addAll(postShopJoiners.stream()
                        .map(PostJoiner::getPostId)
                        .collect(Collectors.toList()));
            }
            // 旅游帖
            List<PostJoiner> postTravelJoiners = joinerList.stream()
                    .filter(joiner -> joiner.getPostType() == 2).collect(Collectors.toList());
            if (postTravelJoiners != null && !postTravelJoiners.isEmpty()) {
                postTravelIdList.addAll(postTravelJoiners.stream()
                        .map(PostJoiner::getPostId)
                        .collect(Collectors.toList()));
            }

//            for (PostJoiner postJoiner : joinerList) {
//                System.out.println("用户进入过拼单帖子id: " + postJoiner.getPostId());
//                PostRoom room = MyStringUtil.getDataInResultObject(
//                        postRoomClient.getPostRoomWithPostIdAndType(
//                                postJoiner.getPostId(), postJoiner.getPostType()), PostRoom.class);
//                if (room != null) {
//                    String roomId = room.getId();
//                    roomMessageVoToUser.setRoomId(roomId);
//                    // 直接发消息为进入房间类型。
//                    rabbitTemplate.convertAndSend(
//                            UserRabbitConfig.EXCHANGE_DIRECT_USER,
//                            UserRabbitConfig.ROUTING_KEY_MESSAGE,
//                            messageToUser);
//                }
//            }
        }
        // 拼单完成流程： 发帖人申请拼单完成， 当所有参与者同意完成后，才可以完成拼单
        // 也可以设置超时时间自动完成 拼单完成后 则将群聊is_deleted置为1

        /** 应该修改成将id和type对应起来 然后搜索帖子状态 帖子状态符合进入群聊才发送进入消息 */
//        Map<Integer, List<String>> postTypeMap = new HashMap<>();
//        List<String> postIdList = new ArrayList<>();

        // 用户发布的拼单
        List<PostRoom> rooms = CommonUtil.getItemsInResultObject(
                postRoomClient.getPostRoomsByUserId(userId),
                PostRoom.class);
        if (rooms != null && !rooms.isEmpty()) {
            List <PostRoom> postShopRooms = rooms.stream()
                    .filter(room -> room.getPostType() == 1)
                    .collect(Collectors.toList());
//            if (postShopIdList != null && !postShopIdList.isEmpty()) {
//                postTypeMap.put(1, postShopIdList);
//            }
            if (postShopRooms != null && !postShopRooms.isEmpty()) {
                postShopIdList.addAll(postShopRooms.stream()
                            .map(PostRoom::getPostId)
                            .collect(Collectors.toList()));
            }

            List<PostRoom> postTravelRooms = rooms.stream()
                    .filter(room -> room.getPostType() == 2)
                    .collect(Collectors.toList());
//            if (postTravelIdList != null && !postTravelIdList.isEmpty()) {
//                postTypeMap.put(2, postTravelIdList);
//            }
            if (postTravelRooms != null && !postTravelRooms.isEmpty()) {
                postTravelIdList.addAll(postTravelRooms.stream()
                        .map(PostRoom::getPostId)
                        .collect(Collectors.toList()));
            }

//            messageToUser.data("message", roomMessageVoToUser);
//            for (PostRoom room : rooms) {
//                String roomId = room.getId();
//                System.out.println("用户进入过群聊id: " + roomId);
//                roomMessageVoToUser.setRoomId(roomId);
//                // 直接发消息为进入房间类型。
//                rabbitTemplate.convertAndSend(
//                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
//                        UserRabbitConfig.ROUTING_KEY_MESSAGE,
//                        messageToUser);
//            }
        }
        List<PostRoom> effectivePostRooms = new ArrayList<>();
        // 拼购帖
        if (!postShopIdList.isEmpty()) {
            List<PostShop> postShopList = CommonUtil.getItemsInResultObject(
                    postClient.getPostShopByIds(postShopIdList),
                    PostShop.class);
            if (postShopList != null) {
                List<PostShop> effectiveShopPost = postShopList.stream()
                        .filter(postShop ->
                                postShop.getPostStatus() > -1 &&
                                        postShop.getPostStatus() < 4)
                        .collect(Collectors.toList());
                if (effectiveShopPost != null) {
                    System.out.println( "======== 2 effectiveShopPost ========");
                    for (int i = 0; i < effectiveShopPost.size(); i++)
                        System.out.println(i + "-effectiveShopPost ==>" + effectiveShopPost.get(i));

                    List<String> effectiveShopPostIds = effectiveShopPost.stream()
                            .map(PostShop::getId).collect(Collectors.toList());
                    /** 有效的帖子id ===> 获取对应的群聊id */
                    List<PostRoom> postShopRoomList = CommonUtil.getItemsInResultObject(
                            postRoomClient.getPostRoomsByPostIdsAndPostType(
                                    effectiveShopPostIds, 1),
                            PostRoom.class);
                    if (postShopRoomList != null && !postShopRoomList.isEmpty()) {
                        effectivePostRooms.addAll(postShopRoomList);
                    }


                }
            }
        }
        if (!postTravelIdList.isEmpty()) {
            List<PostTravel> postTravelList = CommonUtil.getItemsInResultObject(
                    postClient.getPostTravelByIds(postTravelIdList),
                    PostTravel.class);
            if (postTravelList != null) {
                List<PostTravel> effectiveTravelPost = postTravelList.stream()
                        .filter(postShop ->
                                postShop.getPostStatus() > -1 &&
                                        postShop.getPostStatus() < 4)
                        .collect(Collectors.toList());
                if (effectiveTravelPost != null) {
                    System.out.println( "======== 1 effectiveTravelPost ========");
                    for (int i = 0; i < effectiveTravelPost.size(); i++)
                        System.out.println(i + "-effectiveTravelPost ==>" + effectiveTravelPost.get(i));

                    List<String> effectiveTravelPostIds = effectiveTravelPost.stream()
                            .map(PostTravel::getId).collect(Collectors.toList());
                    /** 有效的帖子id ===> 获取对应的群聊id */
                    List<PostRoom> postTravelRoomList = CommonUtil.getItemsInResultObject(
                            postRoomClient.getPostRoomsByPostIdsAndPostType(
                                    effectiveTravelPostIds, 2),
                            PostRoom.class);
                    if (postTravelRoomList != null && !postTravelRoomList.isEmpty()) {
                        effectivePostRooms.addAll(postTravelRoomList);
                    }
                }
            }
        }
        // 存在有效房间 发送进入房间的消息到消息接收队列
        if (!effectivePostRooms.isEmpty()) {
            for (int i = 0; i < effectivePostRooms.size(); i++)
                System.out.println(i + "-effectivePostRoom ==>" + effectivePostRooms.get(i));

            RoomMessageVo roomMessageVoToUser = new RoomMessageVo();
            roomMessageVoToUser.setUserId(userId);
            messageToUser.setActionType(5);
            messageToUser.data("message", roomMessageVoToUser);

            effectivePostRooms.forEach(postRoom -> {
                roomMessageVoToUser.setRoomId(postRoom.getId());
                // 直接发消息为进入房间类型。
                rabbitTemplate.convertAndSend(
                        UserRabbitConfig.EXCHANGE_DIRECT_USER,
                        UserRabbitConfig.ROUTING_KEY_MESSAGE,
                        messageToUser);
            });
        }


//        不需要预先存入set集合 进入行为到处理类的进入方法处理
//        最后转发给用户的消息处理队列 并 添加set集合到redis
        rabbitTemplate.convertAndSend(
                UserRabbitConfig.EXCHANGE_DIRECT_USER,
                UserRabbitConfig.ROUTING_KEY_USER,
                message);

//        if (!roomSet.isEmpty()) {
////            学习到新方法 可以转为数组后自动批量添加
//            redisTemplate.opsForSet().add(userIdAndMessageRoutingKey, roomSet.toArray());
////            逐个添加
////            boolean isAdded = false;
////            for (String roomId : roomSet) {
////                // 没添加过
////                if (! isAdded) {
////                    redisTemplate.opsForSet().add(userIdAndMessageRoutingKey, roomId);
////                    isAdded = true;
////                }
////                redisTemplate.boundSetOps(userIdAndMessageRoutingKey).add(roomId);
////            }
//        }


    }
//    public void loginFailed(ActionTypeAndRoomMessage message) {
//
//    }

    private RoomMessageVo getMessageVo(ActionTypeAndRoomMessage message) {
        return CommonUtil.getMessageInMap(message.getMessageBody(), RoomMessageVo.class);
    }

    /**
     * 转发消息到消息处理队列
     * @param message
     */
    private void deliverTheMessage(ActionTypeAndRoomMessage message) {
        rabbitTemplate.convertAndSend(
                UserRabbitConfig.EXCHANGE_DIRECT_USER,
                UserRabbitConfig.ROUTING_KEY_USER,
                message);
    }

}
